#!/usr/bin/env python3
"""
跨网络数据传输服务器 - 阿里云ECS自动部署工具
支持数据持久化和24/7运行
"""

import os
import sys
import subprocess
import time
from datetime import datetime

class CrossNetworkDeployer:
    def __init__(self):
        self.ecs_ip = ""
        self.deployment_log = []
        
    def log(self, message, level="INFO"):
        """记录日志"""
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        log_entry = f"[{timestamp}] [{level}] {message}"
        print(log_entry)
        self.deployment_log.append(log_entry)
        
    def run_command(self, command, check=True, timeout=300):
        """执行命令"""
        try:
            self.log(f"执行命令: {command}")
            result = subprocess.run(
                command, 
                shell=True, 
                capture_output=True, 
                text=True, 
                timeout=timeout,
                encoding='utf-8'
            )
            
            if result.returncode == 0:
                self.log(f"命令执行成功: {command}")
                return result.stdout.strip()
            else:
                if check:
                    self.log(f"命令执行失败: {command}, 错误: {result.stderr}", "ERROR")
                    raise subprocess.CalledProcessError(result.returncode, command, result.stderr)
                else:
                    self.log(f"命令执行失败但继续: {command}, 错误: {result.stderr}", "WARNING")
                    return None
        except subprocess.TimeoutExpired:
            self.log(f"命令执行超时: {command}", "ERROR")
            raise
        except Exception as e:
            self.log(f"命令执行异常: {command}, 异常: {str(e)}", "ERROR")
            if check:
                raise
            return None
    
    def test_ssh_connection(self):
        """测试SSH连接"""
        self.log("测试SSH连接...")
        try:
            result = self.run_command(
                f'ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no root@{self.ecs_ip} "echo \'SSH connection test successful\'"',
                timeout=15
            )
            if "SSH connection test successful" in result:
                self.log("✅ SSH连接测试成功")
                return True
            else:
                self.log("❌ SSH连接测试失败", "ERROR")
                return False
        except Exception as e:
            self.log(f"❌ SSH连接失败: {str(e)}", "ERROR")
            return False
    
    def create_remote_directory(self):
        """创建远程目录"""
        self.log("创建远程目录...")
        try:
            self.run_command(f'ssh root@{self.ecs_ip} "mkdir -p /root/cross_network_server"')
            self.log("✅ 远程目录创建成功")
            return True
        except Exception as e:
            self.log(f"❌ 创建远程目录失败: {str(e)}", "ERROR")
            return False
    
    def upload_files(self):
        """上传文件"""
        self.log("上传部署文件...")
        
        files_to_upload = [
            ("cross_network_server.py", "/root/cross_network_server/cross_network_server.py"),
            ("deploy_cross_network_server.sh", "/root/cross_network_server/deploy_cross_network_server.sh")
        ]
        
        # 创建临时requirements.txt
        requirements_content = """websockets==11.0.3
asyncio
logging
json
datetime
"""
        with open("temp_requirements.txt", "w", encoding="utf-8") as f:
            f.write(requirements_content)
        
        files_to_upload.append(("temp_requirements.txt", "/root/cross_network_server/requirements.txt"))
        
        try:
            for local_file, remote_path in files_to_upload:
                if not os.path.exists(local_file):
                    self.log(f"❌ 本地文件不存在: {local_file}", "ERROR")
                    return False
                
                self.log(f"上传文件: {local_file} -> {remote_path}")
                self.run_command(f'scp "{local_file}" root@{self.ecs_ip}:"{remote_path}"')
            
            # 清理临时文件
            if os.path.exists("temp_requirements.txt"):
                os.remove("temp_requirements.txt")
            
            self.log("✅ 所有文件上传成功")
            return True
        except Exception as e:
            self.log(f"❌ 文件上传失败: {str(e)}", "ERROR")
            return False
    
    def run_deployment_script(self):
        """运行部署脚本"""
        self.log("执行自动部署脚本...")
        try:
            # 设置脚本权限并执行
            deployment_command = (
                f'ssh root@{self.ecs_ip} "'
                f'cd /root/cross_network_server && '
                f'chmod +x deploy_cross_network_server.sh && '
                f'bash deploy_cross_network_server.sh"'
            )
            
            result = self.run_command(deployment_command, timeout=600)  # 10分钟超时
            self.log("✅ 部署脚本执行完成")
            return True
        except Exception as e:
            self.log(f"❌ 部署脚本执行失败: {str(e)}", "ERROR")
            return False
    
    def verify_deployment(self):
        """验证部署结果"""
        self.log("验证部署结果...")
        
        try:
            # 检查服务状态
            service_status = self.run_command(
                f'ssh root@{self.ecs_ip} "systemctl is-active cross-network-server.service"',
                check=False
            )
            
            if service_status and "active" in service_status:
                self.log("✅ 服务运行正常")
            else:
                self.log(f"⚠️ 服务状态: {service_status}", "WARNING")
            
            # 检查端口监听
            port_check = self.run_command(
                f'ssh root@{self.ecs_ip} "netstat -tlnp | grep :8085"',
                check=False
            )
            
            if port_check:
                self.log("✅ 端口8085监听正常")
            else:
                self.log("⚠️ 端口8085未监听，服务可能正在启动", "WARNING")
            
            return True
        except Exception as e:
            self.log(f"❌ 验证部署失败: {str(e)}", "ERROR")
            return False
    
    def generate_client_config(self):
        """生成Android客户端配置"""
        self.log("生成Android客户端配置文件...")
        
        config_content = f"""// 跨网络数据传输服务器配置
// 自动生成时间: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}

object ServerConfig {{
    // 阿里云ECS服务器地址
    const val WEBSOCKET_URL = "ws://{self.ecs_ip}:8085"
    const val HTTP_URL = "http://{self.ecs_ip}:8085"
    
    // 连接配置
    const val CONNECTION_TIMEOUT = 30000L
    const val RECONNECT_INTERVAL = 5000L
    const val HEARTBEAT_INTERVAL = 30000L
    
    // 服务器信息
    const val SERVER_NAME = "Cross Network Data Server"
    const val SERVER_VERSION = "1.0"
    const val DEPLOY_TIME = "{datetime.now().isoformat()}"
}}

// 使用说明:
// 1. 将此配置更新到你的Android项目中的ServerConfig.kt
// 2. 或者在应用的服务器设置中使用: ws://{self.ecs_ip}:8085
// 3. 重新编译APK: .\\gradlew assembleRelease
// 4. 安装到设备并测试连接
"""
        
        try:
            with open("update_server_config.kt", "w", encoding="utf-8") as f:
                f.write(config_content)
            
            self.log("✅ 客户端配置文件已生成: update_server_config.kt")
            return True
        except Exception as e:
            self.log(f"❌ 生成客户端配置失败: {str(e)}", "ERROR")
            return False
    
    def generate_deployment_report(self):
        """生成部署报告"""
        report_content = f"""跨网络数据传输服务器部署报告
==================================================
部署时间: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
ECS公网IP: {self.ecs_ip}
WebSocket地址: ws://{self.ecs_ip}:8085
服务名称: cross-network-server.service
数据目录: /root/cross_network_server/server_data

部署特性:
- 数据持久化支持 (JSON文件存储)
- 跨网络环境适配
- 自动监控和重启
- 定时数据备份 (每天凌晨2点)
- 24/7稳定运行

管理命令:
- 查看状态: ssh root@{self.ecs_ip} "systemctl status cross-network-server.service"
- 查看日志: ssh root@{self.ecs_ip} "journalctl -u cross-network-server.service -f"
- 重启服务: ssh root@{self.ecs_ip} "systemctl restart cross-network-server.service"
- 停止服务: ssh root@{self.ecs_ip} "systemctl stop cross-network-server.service"

下一步操作:
1. 更新Android应用中的服务器配置
2. 使用新的WebSocket地址: ws://{self.ecs_ip}:8085
3. 重新编译APK
4. 安装并测试应用连接

部署日志:
{"=" * 50}
"""
        
        for log_entry in self.deployment_log:
            report_content += log_entry + "\n"
        
        try:
            with open("CROSS_NETWORK_DEPLOYMENT_REPORT.txt", "w", encoding="utf-8") as f:
                f.write(report_content)
            
            self.log("✅ 部署报告已生成: CROSS_NETWORK_DEPLOYMENT_REPORT.txt")
            return True
        except Exception as e:
            self.log(f"❌ 生成部署报告失败: {str(e)}", "ERROR")
            return False
    
    def deploy(self):
        """执行完整部署流程"""
        print("=" * 60)
        print("  跨网络数据传输服务器 - 阿里云ECS自动部署")
        print("=" * 60)
        print()
        
        print("🎯 部署目标:")
        print("   将带数据持久化功能的WebSocket服务器部署到阿里云ECS")
        print("   支持24/7稳定运行和跨网络环境数据传输")
        print()
        
        print("🔧 推荐ECS配置:")
        print("   - 实例规格: 2核4GB内存 (ecs.g6.large)")
        print("   - 操作系统: Ubuntu 20.04 LTS")
        print("   - 带宽: 5Mbps以上")
        print("   - 存储: 40GB系统盘")
        print("   - 安全组: 开放端口 22, 80, 443, 8085")
        print()
        
        print("💰 预估成本: 约80-120元/月")
        print()
        
        # 获取ECS IP
        while True:
            self.ecs_ip = input("请输入阿里云ECS公网IP地址: ").strip()
            if self.ecs_ip:
                break
            print("❌ IP地址不能为空，请重新输入")
        
        print()
        self.log("开始部署流程...")
        
        # 执行部署步骤
        steps = [
            ("测试SSH连接", self.test_ssh_connection),
            ("创建远程目录", self.create_remote_directory),
            ("上传部署文件", self.upload_files),
            ("执行部署脚本", self.run_deployment_script),
            ("验证部署结果", self.verify_deployment),
            ("生成客户端配置", self.generate_client_config),
            ("生成部署报告", self.generate_deployment_report)
        ]
        
        success_count = 0
        for step_name, step_function in steps:
            try:
                self.log(f"执行步骤: {step_name}")
                if step_function():
                    success_count += 1
                else:
                    self.log(f"步骤失败: {step_name}", "ERROR")
                    break
            except KeyboardInterrupt:
                self.log("用户中断部署", "WARNING")
                break
            except Exception as e:
                self.log(f"步骤异常: {step_name}, 异常: {str(e)}", "ERROR")
                break
        
        # 输出结果
        print()
        print("=" * 60)
        if success_count == len(steps):
            print("         🎉 部署完成！")
            print("=" * 60)
            print()
            print(f"📊 部署信息:")
            print(f"- ECS公网IP: {self.ecs_ip}")
            print(f"- WebSocket地址: ws://{self.ecs_ip}:8085")
            print(f"- 服务名称: cross-network-server.service")
            print(f"- 数据目录: /root/cross_network_server/server_data")
            print()
            print("🎯 恭喜！你的跨网络数据传输服务器现在24/7运行中！")
        else:
            print("         ❌ 部署失败")
            print("=" * 60)
            print()
            print("部分步骤执行失败，请检查上面的错误信息")
            print("可以尝试手动执行失败的步骤")
        
        print()
        print("📋 详细信息请查看:")
        print("- 部署报告: CROSS_NETWORK_DEPLOYMENT_REPORT.txt")
        print("- 客户端配置: update_server_config.kt")
        print()

def main():
    deployer = CrossNetworkDeployer()
    deployer.deploy()

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n\n用户取消部署")
    except Exception as e:
        print(f"\n\n部署过程发生异常: {str(e)}")